﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DefensiveShield
{
    public static partial class OS
    {
        //---------------------------------------------------------------------------------------------------------------------------------
        //---------------------------------------------------------------------------------------------------- SAVE SECRET FILE -----------
        //---------------------------------------------------------------------------------------------------------------------------------
        /**
            @brief Функция сохранения текста в секретный файл
            @param minimalSecrecy - уровень секретности текущей сессии пользователя
             * 
             * Данная функция шифрует переданный ей текст и записывает в указанный файл, ключ шифрования генерируется на ходу при каждом сохранении. При этом ключ должен быть зашифрован на глобальном ключе и записан в FilePassport.
             * 
             * Проверяется, есть ли у пользователя доступ к файлу, в соответствии с дискреционной и мандатной моделью разграничения доступа.
             * 
             * Если гриф, переданный в качестве параметра выше, чем тот, что был у файла раньше, то его необходимо повысить
             * 
             * В случае, если файл не существует, он создаётся и регистрируется, с переносом соответствующих атрибутов пользователя, при этом файл имеет расширение DefensiveShield.Properties.Resources.SecretFileExtention
             * 
            @return код ошибки, при её наличии
        */
        public static ErrorCodes SaveSecretFile(OsSession session, string fileName, string text)
        {
            // TODO: Я изменил комментарий сверху - прочти его ещё раз
            try
            {
                // Дискреционный контроль доступа
                var rights = GetDiscretionalAccessPermission(session, fileName);
                if (rights < Rights.ReadWrite) // У пользователя нет доступа к файлу на запись
                {
                    return ErrorCodes.FileNotWritable;
                }
                // Мандатный контроль доступа
                var mandatoryAccessCode = CheckMandatoryAccessPermission(session, fileName);
                if (mandatoryAccessCode != ErrorCodes.NoError) // Допуск пользователя не ниже грифа файла
                {
                    return mandatoryAccessCode;
                }

                if (Files.ContainsKey(fileName))
                {
                    // Повышение грифа файла, если допуск сессии выше
                    if (session.SessionSecrecy.CompareTo(Files[fileName].SecrecyNum) > 0)
                        Files[fileName].SecrecyNum = session.SessionSecrecy;
                }
                else
                {
                    fileName = fileName.Remove(fileName.LastIndexOf('.')) + DefensiveShield.Properties.Resources.SecretFileExtention;
                    var registerFileCode = RegisterFileSystemObject(session, fileName);
                    if (registerFileCode != ErrorCodes.NoError)
                    {
                        return registerFileCode;
                    }
                    // TODO: В случае если файла нету, то нужно прописать все его права в зависимости от пользователя, который создаёт этот файл (пересмотри каждое поле структуры FilePassport)
                }

                var key = GenerateKey();

                // Зашифрование текста
                var encryptedText = Encrypt(text, key);

                // запись текста в файл
                var fileWriter = new StreamWriter(fileName);
                fileWriter.Write(encryptedText);
                fileWriter.Close();

                return ErrorCodes.NoError;
            }
            catch (Exception)
            {
                return ErrorCodes.UnknownError;
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------
        //---------------------------------------------------------------------------------------------------- SAVE SECRET FILE -----------
        //---------------------------------------------------------------------------------------------------------------------------------
        /**
            @brief Функция открытия секретного файла
             * 
             * Данная функция открывает файл. Если файл не был зарегистрирован в системе, то он открывается как просто не зашифрвоанный текстовый файл, и его содержимое возвращается.
             * Если файл был зарегистрирован в системе, значит он шифрованный, и его нужно расшифровать на ключе, который лежит в структуре о файле, и который сам зашифрован на глоблаьном ключе системы
             * 
             * Проверяется, есть ли у пользователя доступ к файлу, в соответствии с дискреционной и мандатной моделью разграничения доступа.
             * 
            @return string - расшифрованное содержимое файла
            @return null - в случае ошибки
        */

        public static string OpenSecretFile(OsSession session, string fileName)
        {
            try
            {
                var rights = GetDiscretionalAccessPermission(session, fileName);
                if (rights < Rights.Read) // У пользователя нет доступа к файлу на чтение
                {
                    return null;
                }
                // Мандатный контроль доступа
                var mandatoryAccessCode = CheckMandatoryAccessPermission(session, fileName);
                if (mandatoryAccessCode != ErrorCodes.NoError) // Допуск пользователя не ниже грифа файла
                {
                    return null;
                }

                var fileReader = new StreamReader(fileName);
                var text = fileReader.ReadToEnd(); // Считываем файл в строку
                fileReader.Close();
                if (!Files.ContainsKey(fileName)) // Проверяем, зарегистрирован файл или нет
                {
                    return text; // Файл не зарегистрирован, возвращаем содержимое
                }
                else
                {
                    var decryptedText = Decrypt(text, Decrypt(Files[fileName].Key, GlobalKey));
                    return decryptedText; // Файл зарегистрирован, возвращаем расшифрованное содержимое
                }
            }
            catch (Exception)
            {
                return null;
            }
        }
    }
}
